package annuaire.dao.impl;

import java.util.Collection;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.EntityTransaction;
import javax.persistence.NoResultException;
import javax.persistence.Persistence;
import javax.persistence.PersistenceException;
import javax.persistence.Query;

import annuaire.beans.Admin;
import annuaire.beans.Promotion;
import annuaire.beans.Student;
import annuaire.config.DaoConfigLoader;
import annuaire.dao.IAnnuaireDao;
import annuaire.exceptions.DaoException;

/**
 * Classe DAO (Data Access Objet) servant à gérer les objets persistants.
 * 
 * @author Yannick Lorenzati & Stephanie Malakian
 * 
 */

public class JpaAnnuaireDao implements IAnnuaireDao {

	private EntityManagerFactory factory = null;

	final static Integer NB_RESULT_MAX = Integer.parseInt(DaoConfigLoader.getParam("nbResultMax"));

	// Verification basee sur la recherche (methode find()) des caracteres
	// interdits suivants :
	static Pattern MOTIF_CAR = Pattern.compile(DaoConfigLoader.getParam("motifCar")); // Caracteres
	// interdits
	// pour
	// logins et
	// pwds :
	// tout ce
	// qui n'est
	// pas
	// alpha-numerique,
	// underscore
	// ou tiret
	// est
	// rejete
	static Pattern MOTIF_NAMES = Pattern.compile(DaoConfigLoader.getParam("motifNames")); // Caracteres
	// interdits
	// pour
	// tout
	// ce
	// qui
	// est
	// noms,
	// prenoms
	// etc.
	// avec
	// espaces,
	// tirets,
	// acceptes
	static Pattern MOTIF_YEAR = Pattern.compile(DaoConfigLoader.getParam("motifPromoYear")); // PromoYear de la
	// forme
	// 2008/2009
	static Pattern MOTIF_PARAGRAPH = Pattern.compile(DaoConfigLoader.getParam("motifParagraph")); // Caracteres
	// interdits
	// pour un
	// paragraphe.
	static Pattern MOTIF_ADDRESS = Pattern
			.compile(DaoConfigLoader.getParam("motifAddress")); // Adresse :
	// on
	// accepte
	// -/,()
	// espaces,
	// . nombres
	// + lettres
	// + accents
	static Pattern MOTIF_TITLE = Pattern
			.compile(DaoConfigLoader.getParam("motifTitle"));

	// Verification basee sur un motif modele (methode matches()) :
	static String MOTIF_MAIL = DaoConfigLoader.getParam("motifMail"); // Motif
	// pour
	// une
	// adresse
	// e-mail (soit vide avec ^$, soit conforme xxx@hhhh.xx)
	static String MOTIF_WEB = DaoConfigLoader.getParam("motifWeb");

	// Web a
	// raffiner
	// //[a-zA-Z]+((\\.){0,1}[a-zA-Z]+[-_][a-zA-Z]+)*[\\.][a-zA-Z]{2,3}";

	@Override
	/*
	 * (non-Javadoc)
	 * 
	 * @see annuaire.dao.IAnnuaireDao#init()
	 */
	public void init() {
		factory = Persistence.createEntityManagerFactory("annuEtud");
	}

	@Override
	/*
	 * (non-Javadoc)
	 * 
	 * @see annuaire.dao.IAnnuaireDao#close()
	 */
	public void close() {
		if (factory != null) {
			factory.close();
		}
	}

	/* Ouverture et Fermeture securisees de l'Entity Manager */
	private EntityManager newEntityManager() {
		EntityManager em = factory.createEntityManager();
		em.getTransaction().begin();
		return em;
	}

	private void closeEntityManager(EntityManager em) {
		if (em != null) {
			if (em.isOpen()) {
				EntityTransaction t = em.getTransaction();
				if (t.isActive()) {
					try {
						t.rollback();
					} catch (PersistenceException e) {
					}
				}
				em.close();
			}
		}
	}

	@Override
	/*
	 * (non-Javadoc)
	 * 
	 * @see annuaire.dao.IAnnuaireDao#addAdmin(annuaire.beans.Admin)
	 */
	public Admin addAdmin(Admin a) throws DaoException {
		Boolean isValid = true;
		String field = "";

		if (a.getLogin() != null) {
			Matcher m_login = JpaAnnuaireDao.MOTIF_CAR.matcher(a.getLogin());
			if (m_login.find()) {
				isValid = false;
				field = "login";
			}
		}
		if (a.getPwd() != null) {
			Matcher m_pwd = JpaAnnuaireDao.MOTIF_CAR.matcher(a.getPwd());
			if (m_pwd.find()) {
				isValid = false;
				field = "pwd";
			}
		}

		if (!isValid) {
			throw new DaoException(
					"Caractere invalide detecte Administrateur (champ " + field
							+ ")");
		}

		// Si aucun caract�re invalide : on ajoute en base
		EntityManager em = null;
		try {

			em = newEntityManager();
			em.persist(a);
			em.getTransaction().commit();
			System.err.println("DAO : addAdmin with id = " + a.getId());
			return a;
		} catch (PersistenceException px) {
			px.printStackTrace();
			throw new DaoException(px);
		} finally {
			closeEntityManager(em);
		}
	}

	@Override
	/*
	 * (non-Javadoc)
	 * 
	 * @see annuaire.dao.IAnnuaireDao#addPromo(annuaire.beans.Promotion)
	 */
	public Promotion addPromo(Promotion p) throws DaoException {
		Boolean isValid = true;
		String field = "";

		if (p.getPromoYear() != null) {
			Matcher m_promoYear = JpaAnnuaireDao.MOTIF_YEAR.matcher(p
					.getPromoYear());
			if (m_promoYear.find()) {
				isValid = false;
				field = "promoYear";
			}
		}
		if (p.getTitle() != null) {
			Matcher m_title = JpaAnnuaireDao.MOTIF_TITLE.matcher(p.getTitle());
			if (m_title.find()) {
				isValid = false;
				field = "title";
			}
		}
		if (p.getDescription() != null) {
			Matcher m_description = JpaAnnuaireDao.MOTIF_PARAGRAPH.matcher(p
					.getDescription());
			if (m_description.find()) {
				isValid = false;
				field = "description";
			}
		}

		if (!isValid) {
			throw new DaoException(
					"Caractere invalide detecte dans promotion (champ " + field
							+ ")");
		}

		// Si aucun caract�re invalide : on ajoute en base
		EntityManager em = null;
		try {
			em = newEntityManager();
			em.persist(p);
			em.getTransaction().commit();
			System.err.println("DAO : addPromotion with id = " + p.getId());
			return p;
		} catch (PersistenceException px) {
			px.printStackTrace();
			throw new DaoException(px);
		} finally {
			closeEntityManager(em);
		}
	}

	@Override
	/*
	 * (non-Javadoc)
	 * 
	 * @see annuaire.dao.IAnnuaireDao#addStudent(annuaire.beans.Student)
	 */
	public Student addStudent(Student s) throws DaoException {
		Boolean isValid = true;
		String msg = "";

		if (s.getName() != null) {
			Matcher m_name = JpaAnnuaireDao.MOTIF_NAMES.matcher(s.getName());
			if (m_name.find()) {
				isValid = false;
				msg = "Caractere invalide detecte dans le nom";
			}
		}
		if (s.getFirstName() != null) {
			Matcher m_firstName = JpaAnnuaireDao.MOTIF_NAMES.matcher(s
					.getFirstName());
			if (m_firstName.find()) {
				isValid = false;
				msg = "Caractere invalide detecte dans le prenom";
			}
		}
		if (s.getLogin() != null) {
			Matcher m_login = JpaAnnuaireDao.MOTIF_CAR.matcher(s.getLogin());
			if (m_login.find()) {
				isValid = false;
				msg = "Caractere invalide detecte dans le login";
			}
		}
		if (s.getPwd() != null) {
			Matcher m_pwd = JpaAnnuaireDao.MOTIF_CAR.matcher(s.getPwd());
			if (m_pwd.find()) {
				isValid = false;
				msg = "Caractere invalide detecte dans le mot de passe";
			}
		}
		if (s.getAddress() != null) {
			Matcher m_address = JpaAnnuaireDao.MOTIF_ADDRESS.matcher(s
					.getAddress());
			if (m_address.find()) {
				isValid = false;
				msg = "Caractere invalide detecte dans l'adresse";
			}
		}

		if (s.getMail() != null) {
			// Si le s.getMail() ne correspond pas au motif MOTIF_MAIL : isValid
			// = false
			if (!s.getMail().matches(JpaAnnuaireDao.MOTIF_MAIL)) {
				isValid = false;
				msg = "Adresse mail invalide";
			}
		}

		if (s.getWeb() != null) {
			// Si le s.getWeb() ne correspond pas au motif MOTIF_WEB : isValid =
			// false
			if (!s.getWeb().matches(JpaAnnuaireDao.MOTIF_WEB)) {
				isValid = false;
				msg = "Adresse web invalide";
			}
		}

		if (s.getSociety() != null) {
			Matcher m_society = JpaAnnuaireDao.MOTIF_NAMES.matcher(s
					.getSociety());
			if (m_society.find()) {
				isValid = false;
				msg = "Caractere invalide detecte dans le nom de la societe";
			}
		}
		if (s.getComments() != null) {
			Matcher m_comments = JpaAnnuaireDao.MOTIF_PARAGRAPH.matcher(s
					.getComments());
			if (m_comments.find()) {
				isValid = false;
				msg = "Caractere invalide detecte dans le commentaire";
			}
		}

		if (!isValid) {
			throw new DaoException(msg);
		}

		EntityManager em = null;
		try {
			em = newEntityManager();
			em.persist(s);
			em.getTransaction().commit();
			System.err.println("DAO : addStudent with id = " + s.getId());
			return s;
		} catch (PersistenceException px) {
			px.printStackTrace();
			throw new DaoException(px);
		} finally {
			closeEntityManager(em);
		}
	}

	@Override
	/*
	 * (non-Javadoc)
	 * 
	 * @see annuaire.dao.IAnnuaireDao#removeAdmin(annuaire.beans.Admin)
	 */
	public void removeAdmin(Admin a) throws DaoException {
		EntityManager em = null;
		Admin a2 = null;
		try {
			// Ici on ne peut pas utiliser les methodes newEntityManager et
			// closeEntityManager
			em = factory.createEntityManager();
			a2 = em.find(Admin.class, a.getId());

			if (a2 != null) {
				em.getTransaction().begin();
				em.remove(a2);
				System.err.println("Dao : removeAdmin with id=" + a2.getId());
				em.getTransaction().commit();
			} else {
				throw new DaoException("Administrateur inexistant");
			}
		} catch (PersistenceException px) {
			px.printStackTrace();
			throw new DaoException(px);
		} finally {
			if (em != null) {
				em.close();
			}
		}
	}

	@Override
	/*
	 * (non-Javadoc)
	 * 
	 * @see annuaire.dao.IAnnuaireDao#removePromo(annuaire.beans.Promotion)
	 */
	public void removePromo(Promotion p) throws DaoException {
		EntityManager em = null;
		Promotion p2 = null;
		try {
			// Ici on ne peut pas utiliser les methodes newEntityManager et
			// closeEntityManager
			em = factory.createEntityManager();
			p2 = em.find(Promotion.class, p.getId());

			if (p2 != null) {
				em.getTransaction().begin();
				em.remove(p2);
				System.err.println("Dao : removePromo with id=" + p2.getId());
				em.getTransaction().commit();
			} else {
				throw new DaoException("Promotion inexistante");
			}
		} catch (PersistenceException px) {
			px.printStackTrace();
			throw new DaoException(px);
		} finally {
			if (em != null) {
				em.close();
			}
		}
	}

	@Override
	/*
	 * (non-Javadoc)
	 * 
	 * @see annuaire.dao.IAnnuaireDao#removeStudent(annuaire.beans.Student)
	 */
	public void removeStudent(Student s) throws DaoException {
		EntityManager em = null;
		Student s2 = null;
		try {
			// Ici on ne peut pas utiliser les methodes newEntityManager et
			// closeEntityManager
			em = factory.createEntityManager();
			s2 = em.find(Student.class, s.getId());

			if (s2 != null) {
				em.getTransaction().begin();
				em.remove(s2);
				System.err.println("Dao : removeStudent with id=" + s2.getId());
				em.getTransaction().commit();
			} else {
				throw new DaoException("Etudiant inexistant");
			}
		} catch (PersistenceException px) {
			px.printStackTrace();
			throw new DaoException(px);
		} finally {
			if (em != null) {
				em.close();
			}
		}
	}

	@Override
	/*
	 * (non-Javadoc)
	 * 
	 * @see annuaire.dao.IAnnuaireDao#updateAdmin(annuaire.beans.Admin)
	 */
	public Admin updateAdmin(Admin a) throws DaoException {
		EntityManager em = null;
		try {
			if (a != null) {
				em = newEntityManager();
				a = em.merge(a);
				em.getTransaction().commit();
				System.err.println("Dao : updateAdmin with id=" + a.getId());
			}
			return a;
		} catch (PersistenceException px) {
			px.printStackTrace();
			throw new DaoException(px);
		} finally {
			closeEntityManager(em);
		}
	}

	@Override
	/*
	 * (non-Javadoc)
	 * 
	 * @see annuaire.dao.IAnnuaireDao#updatePromo(annuaire.beans.Promotion)
	 */
	public Promotion updatePromo(Promotion p) throws DaoException {
		EntityManager em = null;
		try {
			if (p != null) {
				em = newEntityManager();
				p = em.merge(p);
				em.getTransaction().commit();
				System.err.println("Dao : updatePromo with id=" + p.getId());
			}
			return p;
		} catch (PersistenceException px) {
			px.printStackTrace();
			throw new DaoException(px);
		} finally {
			closeEntityManager(em);
		}
	}

	@Override
	/*
	 * (non-Javadoc)
	 * 
	 * @see annuaire.dao.IAnnuaireDao#updateStudent(annuaire.beans.Student)
	 */
	public Student updateStudent(Student s) throws DaoException {
		EntityManager em = null;
		try {
			if (s != null) {
				em = newEntityManager();
				s = em.merge(s);
				em.getTransaction().commit();
				System.err.println("Dao : updateStudent with id=" + s.getId());
			}
			return s;
		} catch (PersistenceException px) {
			px.printStackTrace();
			throw new DaoException(px);
		} finally {
			closeEntityManager(em);
		}
	}

	@SuppressWarnings("unchecked")
	@Override
	/*
	 * (non-Javadoc)
	 * 
	 * @see annuaire.dao.IAnnuaireDao#listPromotions()
	 */
	public Collection<Integer> listPromotions() throws DaoException {
		EntityManager em = null;
		try {
			em = newEntityManager();

			String req = "SELECT id FROM Promotion";

			Query q = em.createQuery(req);

			em.getTransaction().commit();
			if (q.getResultList().size() > 0) {
				return q.getResultList();
			} else {
				return null;
			}
		} catch (PersistenceException px) {
			px.printStackTrace();
			throw new DaoException(px);
		} finally {
			closeEntityManager(em);
		}
	}

	@SuppressWarnings("unchecked")
	@Override
	/*
	 * (non-Javadoc)
	 * 
	 * @see annuaire.dao.IAnnuaireDao#listStudents(java.lang.Integer)
	 */
	public Collection<Integer> listStudents(int idPromo) throws DaoException {
		EntityManager em = null;
		try {
			em = newEntityManager();

			String req = "SELECT id FROM Student AS s WHERE s.promo = "
					+ idPromo;

			Query q = em.createQuery(req);

			em.getTransaction().commit();
			if (q.getResultList().size() > 0) {
				return q.getResultList();
			} else {
				return null;
			}
		} catch (PersistenceException px) {
			px.printStackTrace();
			throw new DaoException(px);
		} finally {
			closeEntityManager(em);
		}
	}

	@SuppressWarnings("unchecked")
	@Override
	/*
	 * (non-Javadoc)
	 * 
	 * @see annuaire.dao.IAnnuaireDao#searchAdmin(annuaire.beans.Admin,
	 * java.lang.Integer)
	 */
	public Collection<Admin> searchAdmin(Admin pattern, Integer nbResult)
			throws DaoException {

		EntityManager em = null;

		try {
			em = newEntityManager();

			if (pattern == null) {
				throw new DaoException(
						"Le pattern de recherche doit etre different de null");
			} else if (nbResult < 0 || nbResult > JpaAnnuaireDao.NB_RESULT_MAX) {
				throw new DaoException(
						"La constante limitant le nombre de resultats est invalide");
			}

			else {
				// Insensible a la casse => pas la peine de lower()
				String req = "SELECT a FROM Admin a WHERE a.login LIKE ?1)";

				Query q = em.createQuery(req).setParameter(1,
						pattern.getLogin());

				q = q.setMaxResults(nbResult); // On limite le nombre de
				// resultats

				em.getTransaction().commit();

				if (q.getResultList().size() > 0) {
					return q.getResultList();
				} else {
					return null;
				}
			}
		} catch (PersistenceException px) {
			px.printStackTrace();
			throw new DaoException(px);
		} finally {
			closeEntityManager(em);
		}
	}

	@Override
	public Admin searchAdminById(int idAdmin) throws DaoException {
		EntityManager em = null;
		Admin aRes = null;

		try {
			em = newEntityManager();

			if (idAdmin < 0) {
				throw new DaoException("Id admin invalide");
			}

			else {
				String req = "SELECT a FROM Admin a WHERE a.id = ?1";

				Query q = em.createQuery(req).setParameter(1, idAdmin);

				em.getTransaction().commit();

				aRes = (Admin) q.getSingleResult();
				return aRes;
			}
		} catch (NoResultException n) {
			return null;
		} catch (PersistenceException px) {
			px.printStackTrace();
			throw new DaoException(px);
		} finally {
			closeEntityManager(em);
		}
	}

	@SuppressWarnings("unchecked")
	@Override
	/*
	 * (non-Javadoc)
	 * 
	 * @see annuaire.dao.IAnnuaireDao#searchPromo(annuaire.beans.Promotion,
	 * java.lang.boolean, java.lang.Integer)
	 */
	public Collection<Promotion> searchPromo(Promotion pattern,
			boolean withStudents, Integer nbResult) throws DaoException {

		EntityManager em = null;
		EntityManager em2 = null;
		int cpt_criteres = 0; // pour savoir si on met AND dans la requete
		// (concatenation)

		try {
			em = newEntityManager();

			if (pattern == null
					|| (pattern.getPromoYear() == null
							&& pattern.getTitle() == null && pattern
							.getDescription() == null)) {
				throw new DaoException(
						"Le pattern de recherche doit etre different de null");
			}

			else if (nbResult < 0 || nbResult > JpaAnnuaireDao.NB_RESULT_MAX) {
				throw new DaoException(
						"La constante limitant le nombre de resultats est invalide");
			}

			else { // pattern not null et nbResult valide

				// promoYear
				String reqs = "SELECT p FROM Promotion p WHERE ";
				if (pattern.getPromoYear() != null) {
					reqs += "p.promoYear LIKE :r_promoYear ";
					cpt_criteres++;
				}

				// title
				if (pattern.getTitle() != null) {
					if (cpt_criteres > 0) {
						reqs += " AND p.title LIKE :r_title ";
					} else if (cpt_criteres == 0) {
						reqs += " p.title LIKE :r_title ";
					}
					cpt_criteres++;
				}

				// description
				if (pattern.getDescription() != null) {
					if (cpt_criteres > 0) {
						reqs += " AND p.description LIKE :r_description ";
					} else if (cpt_criteres == 0) {
						reqs += "p.description LIKE :r_description ";
					}
					cpt_criteres++;
				}

				Query qs = em.createQuery(reqs);

				// Ajout des parametres a la requete selon les champs vides ou
				// pas :
				if (pattern.getPromoYear() != null) {
					qs = qs.setParameter("r_promoYear", pattern.getPromoYear());
				}
				if (pattern.getTitle() != null) {
					qs = qs.setParameter("r_title", pattern.getTitle());
				}
				if (pattern.getDescription() != null) {
					qs = qs.setParameter("r_description", pattern
							.getDescription());
				}

				qs = qs.setMaxResults(nbResult); // On limite le nombre de
				// resultats

				em.getTransaction().commit();

				// Si la requete renvoie au moins un resultat
				if (qs.getResultList().size() > 0) {
					// Si on ne veut pas les etudiants de la promo
					if (!withStudents) {
						// Mettre a nill la liste de students de chaque
						// promo de la list list_promos
						Collection<Promotion> list_promos = qs.getResultList();
						for (Promotion i_promo : list_promos) {
							i_promo.setListStudents(null);
						}
						return qs.getResultList();
					} else { // Si on veut renvoyer les etudiants de la promo en
						// +

						Collection<Promotion> list_promos = qs.getResultList();

						try {
							// Aller chercher la liste de students de chaque
							// promo de la list list_promos
							for (Promotion i_promo : list_promos) {

								em2 = newEntityManager();

								String req2 = "SELECT s FROM Student s WHERE s.promo = "
										+ i_promo.getId();
								Query q2 = em2.createQuery(req2);
								em2.getTransaction().commit();

								i_promo.setListStudents(q2.getResultList());
							}
							return list_promos;
						} finally {
							closeEntityManager(em2);
						}
					} // Fin du else withStudents
				} // Fin if(qs.getResultList().size() > 0)
				else {
					return null;
				}
			} // fin else pattern not null

		} // fin try

		catch (PersistenceException px) {
			px.printStackTrace();
			throw new DaoException(px);
		} finally {
			closeEntityManager(em);
		}
	}

	@SuppressWarnings("unchecked")
	@Override
	public Promotion searchPromoById(int idPromo, boolean withStudents)
			throws DaoException {
		EntityManager em = null;
		EntityManager em2 = null;
		Promotion pRes = null;

		try {
			em = newEntityManager();

			if (idPromo < 0) {
				throw new DaoException("Id promo invalide");
			}

			else {
				String req = "SELECT p FROM Promotion p WHERE p.id = ?1";

				Query q = em.createQuery(req).setParameter(1, idPromo);

				em.getTransaction().commit();

				pRes = (Promotion) q.getSingleResult();

				if (!withStudents) {
					// Mettre a nill la liste de students de pRes
					pRes.setListStudents(null);
					return pRes;
				} else {
					// Si on veut renvoyer les etudiants de la promo en
					// +

					try {
						em2 = newEntityManager();

						String req2 = "SELECT s FROM Student s WHERE s.promo = "
								+ pRes.getId();
						Query q2 = em2.createQuery(req2);
						em2.getTransaction().commit();

						pRes.setListStudents(q2.getResultList());

						return pRes;
					} finally {
						closeEntityManager(em2);
					}
				} // Fin du else withStudents
			}
		} catch (NoResultException n) {
			return null;
		} catch (PersistenceException px) {
			px.printStackTrace();
			throw new DaoException(px);
		} finally {
			closeEntityManager(em);
		}
	}

	@SuppressWarnings("unchecked")
	@Override
	/*
	 * (non-Javadoc)
	 * 
	 * @see annuaire.dao.IAnnuaireDao#searchStudents(annuaire.beans.Student,
	 * java.lang.Integer)
	 */
	public Collection<Student> searchStudents(Student pattern, Integer nbResult)
			throws DaoException {

		EntityManager em = null;
		int cpt_criteres = 0; // pour savoir si on met AND dans la requete
		// (concatenation)

		try {
			em = newEntityManager();

			if (pattern == null
					|| (pattern.getLogin() == null && pattern.getPwd() == null
							&& pattern.getName() == null
							&& pattern.getFirstName() == null
							&& pattern.getAddress() == null
							&& pattern.getMail() == null
							&& pattern.getWeb() == null
							&& pattern.getSociety() == null
							&& pattern.getComments() == null && pattern
							.getLastUpdate() == null)) {
				throw new DaoException(
						"Le pattern de recherche doit etre different de null");
			}

			else if (nbResult < 0 || nbResult > JpaAnnuaireDao.NB_RESULT_MAX) {
				throw new DaoException(
						"La constante limitant le nombre de resultats est invalide");
			}

			else { // pattern not null et nbResult valide

				// login
				String reqs = "SELECT s FROM Student s WHERE ";
				if (pattern.getLogin() != null && !pattern.getLogin().isEmpty()) {
					reqs += "s.login LIKE :r_login ";
					cpt_criteres++;
				}

				// name
				if (pattern.getName() != null && !pattern.getName().isEmpty()) {
					if (cpt_criteres > 0) {
						reqs += " AND s.name LIKE :r_name ";
					} else if (cpt_criteres == 0) {
						reqs += " s.name LIKE :r_name ";
					}
					cpt_criteres++;
				}

				// firstName
				if (pattern.getFirstName() != null && !pattern.getFirstName().isEmpty()) {
					if (cpt_criteres > 0) {
						reqs += " AND s.firstName LIKE :r_firstName ";
					} else if (cpt_criteres == 0) {
						reqs += " s.firstName LIKE :r_firstName ";
					}
					cpt_criteres++;
				}

				// address
				if (pattern.getAddress() != null && !pattern.getAddress().isEmpty()) {
					if (cpt_criteres > 0) {
						reqs += " AND s.address LIKE :r_address ";
					} else if (cpt_criteres == 0) {
						reqs += " s.address LIKE :r_address ";
					}
					cpt_criteres++;
				}

				// mail
				if (pattern.getMail() != null && !pattern.getMail().isEmpty()) {
					if (cpt_criteres > 0) {
						reqs += " AND s.mail LIKE :r_mail ";
					} else if (cpt_criteres == 0) {
						reqs += " s.mail LIKE :r_mail ";
					}
					cpt_criteres++;
				}

				// web
				if (pattern.getWeb() != null && !pattern.getWeb().isEmpty()) {
					if (cpt_criteres > 0) {
						reqs += " AND s.web LIKE :r_web ";
					} else if (cpt_criteres == 0) {
						reqs += " s.web LIKE :r_web ";
					}
					cpt_criteres++;
				}

				// society
				if (pattern.getSociety() != null && !pattern.getSociety().isEmpty()) {
					if (cpt_criteres > 0) {
						reqs += " AND s.society LIKE :r_society ";
					} else if (cpt_criteres == 0) {
						reqs += " s.society LIKE :r_society ";
					}
					cpt_criteres++;
				}

				// comments
				if (pattern.getComments() != null && !pattern.getComments().isEmpty()) {
					if (cpt_criteres > 0) {
						reqs += " AND s.comments LIKE :r_comments ";
					} else if (cpt_criteres == 0) {
						reqs += " s.comments LIKE :r_comments ";
					}
					cpt_criteres++;
				}

				// lastUpdate
				if (pattern.getLastUpdate() != null) {
					if (cpt_criteres > 0) {
						reqs += " AND s.lastUpdate = :r_lastUpdate";
					} else if (cpt_criteres == 0) {
						reqs += " s.lastUpdate = :r_lastUpdate";
					}
					cpt_criteres++;
				}

				Query qs = em.createQuery(reqs);

				// Ajout des parametres a la requete selon les champs vides ou
				// pas :
				if (pattern.getLogin() != null  && !pattern.getLogin().isEmpty()) {
					qs = qs.setParameter("r_login", pattern.getLogin());
				}
				if (pattern.getName() != null  && !pattern.getName().isEmpty()) {
					qs = qs.setParameter("r_name", pattern.getName());
				}
				if (pattern.getFirstName() != null && !pattern.getFirstName().isEmpty()) {
					qs = qs.setParameter("r_firstName", pattern.getFirstName());
				}
				if (pattern.getAddress() != null && !pattern.getAddress().isEmpty()) {
					qs = qs.setParameter("r_address", pattern.getAddress());
				}
				if (pattern.getMail() != null && !pattern.getMail().isEmpty()) {
					qs = qs.setParameter("r_mail", pattern.getMail());
				}
				if (pattern.getWeb() != null && !pattern.getWeb().isEmpty()) {
					qs = qs.setParameter("r_web", pattern.getWeb());
				}
				if (pattern.getSociety() != null && !pattern.getSociety().isEmpty()) {
					qs = qs.setParameter("r_society", pattern.getSociety());
				}
				if (pattern.getComments() != null && !pattern.getComments().isEmpty()) {
					qs = qs.setParameter("r_comments", pattern.getComments());
				}
				if (pattern.getLastUpdate() != null) {
					qs = qs.setParameter("r_lastUpdate", pattern
							.getLastUpdate());
				}

				qs = qs.setMaxResults(nbResult); // On limite le nombre de
				// resultats

				em.getTransaction().commit();
				if (qs.getResultList().size() > 0) {
					return qs.getResultList();
				} else {
					return null;
				}
			} // fin else pattern not null

		} // fin try

		catch (PersistenceException px) {
			px.printStackTrace();
			throw new DaoException(px);
		} finally {
			closeEntityManager(em);
		}
	}

	@Override
	public Student searchStudentById(int idStudent) throws DaoException {
		EntityManager em = null;
		Student sRes = null;

		try {
			em = newEntityManager();

			if (idStudent < 0) {
				throw new DaoException("Id student invalide");
			}

			else {
				String req = "SELECT s FROM Student s WHERE s.id = ?1";

				Query q = em.createQuery(req).setParameter(1, idStudent);

				em.getTransaction().commit();

				sRes = (Student) q.getSingleResult();
				return sRes;
			}
		} catch (NoResultException n) {
			return null;
		} catch (PersistenceException px) {
			px.printStackTrace();
			throw new DaoException(px);
		} finally {
			closeEntityManager(em);
		}
	}

	@Override
	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * annuaire.dao.IAnnuaireDao#addStudentsToPromo(annuaire.beans.Promotion,
	 * java.util.Collection<annuaire.beans.Student>)
	 */
	public Promotion addStudentsToPromo(Promotion p,
			Collection<Student> students) throws DaoException {
		for (Student i_student : students) {
			i_student.setPromo(p);
			updateStudent(i_student); // Un update de chaque Student est
			// necessaire pour rendre effective
			// l'association a une Promotion :
		}
		p.setListStudents(students);
		return p;
	}

	@SuppressWarnings("unchecked")
	@Override
	public Collection<Integer> listStudents() throws DaoException {
		EntityManager em = null;
		try {
			em = newEntityManager();

			String req = "SELECT id FROM Student";

			Query q = em.createQuery(req);

			em.getTransaction().commit();
			if (q.getResultList().size() > 0) {
				return q.getResultList();
			} else {
				return null;
			}
		} catch (PersistenceException px) {
			px.printStackTrace();
			throw new DaoException(px);
		} finally {
			closeEntityManager(em);
		}
	}

}
